package com.example.demo.widget.chart.pie

import android.graphics.Paint
import android.graphics.PointF
import android.graphics.RectF
import com.example.demo.Logger
import com.example.demo.widget.chart.ChartItem
import com.example.demo.widget.chart.utils.MathUtils
import kotlin.math.*

/**
 * ChartComment帮助类
 *
 * @author wangheng
 */
class PieChartHelper {
    companion object {
        private const val TAG = "PieChartHelper"
    }
    var mCommentLineSize = 1f
    var mCenterX = 0f
    var mCenterY = 0f
    var mRadius = 100f
    var mChartSize = 0f
    var mCommentTopTextPaint: Paint? = null
    var mCommentTopTextPadding = 0f
    var mCommentBottomTextPaint: Paint? = null
    var mCommentBottomTextPadding = 0f
    var mList: ArrayList<ChartItem>? = null
    var mDrawRect = RectF()
    var mLeftRightSpace = 0f
    var mOutRadius = 0f

    fun calculateCommentInfo(){

        val list = mList
        if(list == null || list.isEmpty()){
            return
        }
        mOutRadius = mRadius + mLeftRightSpace / 2f
        val size = list.size
        for(index in 0 until size){
            val item = list[index]
            // 计算在第几部分
            item.calculatePiePartInChart()
            // 得到圆上开始点
            getCommentStartPointInCircle(item)
            // 得到文字y轴位置
            getCommentContentLocation(list,index,item)
        }
    }

    private fun getCommentContentLocation(list: ArrayList<ChartItem>, index: Int, item: ChartItem) {
        val topTextLength = mCommentTopTextPaint?.measureText(item.title) ?: 0f
        val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextLength = mCommentBottomTextPaint?.measureText(item.subTitle) ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        val halfLineSize = mCommentLineSize / 2f
        val maxTextLength = max(topTextLength,bottomTextLength)
        val part = item.partInChart

        val bottomHeight = halfLineSize + bottomTextSize + mCommentBottomTextPadding * 2
        val topHeight = halfLineSize + topTextSize + mCommentTopTextPadding * 2

        if(index == 0){
            // 小于45度的做特殊处理
            val topRightCount = getTopRightCount()
            if(topRightCount <= 1) {
                val secondPoint = MathUtils.getPointF(
                    mCenterX,
                    mCenterY,
                    mOutRadius,
                    item.startAngle + item.swipeAngle / 2)
                item.setSecondPointValue(secondPoint)
            }else{
                val secondPoint = PointF()
                secondPoint.x = item.firstPoint.x
                secondPoint.y = topTextSize + 2 * mCommentTopTextPadding + mCommentLineSize / 2f
                item.setSecondPointValue(secondPoint)
            }
        }else{
            val pre = list[index - 1]
            val prePart = pre.partInChart
            if(prePart == part){     // 如果与上一个在同一个区域内
                if(prePart == ChartItem.PART_1){        // 在圆心右边边
                    val angle = item.startAngle + item.swipeAngle / 2
                    val preBottom = pre.secondPoint.y + bottomHeight
                    val secondPoint = MathUtils.getPointF(mCenterX,mCenterY,mOutRadius,angle)
                    val yDelta = secondPoint.y - topHeight  - preBottom
                    Logger.i(TAG,"${item.title},pre second y:${pre.secondPoint.y},current second y,${secondPoint.y},delta:$yDelta")
                    if(yDelta < 0){
                        secondPoint.y = secondPoint.y - yDelta
                        var sinValue = (secondPoint.y - mCenterY) / mOutRadius
                        if (sinValue < -1){
                            sinValue = -1f
                        }else if(sinValue > 1){
                            sinValue = 1f
                        }
                        val radian = -asin(sinValue)
                        val xDelta = cos(radian) * mOutRadius
                        Logger.i(TAG,"${item.startAngle + item.swipeAngle /2f},${item.title}##########${xDelta.roundToInt()}")
                        secondPoint.x = mCenterX + xDelta
                        if(secondPoint.x <= item.firstPoint.x){
                            secondPoint.x = (item.firstPoint.x + (mDrawRect.right - item.firstPoint.x) / 2f)
                        }
                    }
                    // 小于45度的做特殊处理
                    if (isTopRightAngle(angle)){
                        secondPoint.y = pre.secondPoint.y + getCommentContentHeight()
                    }
                    item.setSecondPointValue(secondPoint)
                }else{      // 在圆心左边
                    val preTop = pre.secondPoint.y - topHeight
                    val secondPoint = MathUtils.getPointF(mCenterX,mCenterY,mOutRadius,item.startAngle + item.swipeAngle / 2)

                    val yDelta = secondPoint.y + bottomHeight - preTop
                    if(yDelta > 0){
                        secondPoint.y = secondPoint.y + yDelta
                        var sinValue = (secondPoint.y - mCenterY) / mOutRadius
                        if (sinValue < -1){
                            sinValue = -1f
                        }else if(sinValue > 1){
                            sinValue = 1f
                        }
                        val radian = -asin(sinValue)
                        val xDelta = cos(radian) * mOutRadius
                        Logger.i(TAG,"${item.startAngle + item.swipeAngle /2f},${item.title}##########${xDelta.roundToInt()}")
                        secondPoint.x = mCenterX - xDelta
                        if(secondPoint.x >= item.firstPoint.x){
                            secondPoint.x = (item.firstPoint.x + (item.firstPoint.x - mDrawRect.right) / 2f)
                        }
                    }

                    item.setSecondPointValue(secondPoint)
                }
            }else{      // 跟上一边不一致
                Logger.i(TAG,"part not same:${item.title}:::${item.startAngle + item.swipeAngle /2f}")
                val secondPoint = MathUtils.getPointF(mCenterX,mCenterY,mOutRadius,item.startAngle + item.swipeAngle / 2)
                Logger.i(TAG,"part not same:${item.title}:::${secondPoint.x},${secondPoint.y}")
                item.setSecondPointValue(secondPoint)
            }
        }
        Logger.i(TAG,"${item.title}:part:${item.partInChart},location:(${item.secondPoint.x},${item.secondPoint.y})")
        if(part == ChartItem.PART_1){       // 如果是第一部分(右边)
            val length = min(maxTextLength,mDrawRect.right - item.secondPoint.x)
            item.thirdPoint.x = item.secondPoint.x + length
            item.thirdPoint.y = item.secondPoint.y

            item.titleRect.top = item.secondPoint.y - halfLineSize - mCommentTopTextPadding - topTextSize
            item.titleRect.bottom = item.titleRect.top + topTextSize
            item.titleRect.right = item.secondPoint.x + length
            item.titleRect.left = item.titleRect.right - max(length,topTextLength)

            item.subTitleRect.top = item.secondPoint.y + halfLineSize + mCommentBottomTextPadding
            item.subTitleRect.bottom = item.subTitleRect.top + bottomTextSize
            item.subTitleRect.right = item.secondPoint.x + length
            item.subTitleRect.left = item.subTitleRect.right - max(length,bottomTextLength)
        }else{      // 在第二部分(左边)
            val length = min(maxTextLength,item.secondPoint.x - mDrawRect.left)
            item.thirdPoint.x = item.secondPoint.x - length
            item.thirdPoint.y = item.secondPoint.y

            item.titleRect.top = item.secondPoint.y - halfLineSize - mCommentTopTextPadding - topTextSize
            item.titleRect.bottom = item.titleRect.top + topTextSize
            item.titleRect.left = item.thirdPoint.x
            item.titleRect.right = item.titleRect.left + max(length,maxTextLength)

            item.subTitleRect.top = item.secondPoint.y + halfLineSize + mCommentBottomTextPadding
            item.subTitleRect.bottom = item.subTitleRect.top + bottomTextSize
            item.subTitleRect.left = item.thirdPoint.x
            item.subTitleRect.right = item.subTitleRect.left + max(length,maxTextLength)
        }

    }


    private fun getItemCommentContentRect(item: ChartItem): RectF{
        val rect = RectF()
        rect.top = item.titleRect.top - mCommentTopTextPadding
        rect.left = item.secondPoint.x
        rect.right = item.thirdPoint.x
        rect.bottom = item.subTitleRect.bottom + mCommentBottomTextPadding
        return rect
    }

    private fun getCommentContentHeight(): Float{
        val topTextSize =  mCommentTopTextPaint?.textSize ?: 0f
        val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
        return mCommentTopTextPadding * 2 + mCommentBottomTextPadding * 2 + topTextSize + bottomTextSize + mCommentLineSize
    }

    // 得到圆上的开始点的坐标
    private fun getCommentStartPointInCircle(item: ChartItem) {
        val radius = mRadius + mChartSize / 2f
        val angle = item.startAngle + item.swipeAngle / 2f
        item.firstPoint = MathUtils.getPointF(
            mCenterX,
            mCenterY,
            radius,
            angle
        )
    }

    private fun isTopRightAngle(angle: Float): Boolean{
        return (angle >= -90 && angle < -45)
    }

    private fun getTopRightCount(): Int {
        val list = mList
        if(list == null || list.size == 0){
            return 0
        }
        var topRightCount = 0
        list.forEach {
            val angle = it.startAngle + it.swipeAngle / 2f
            if(isTopRightAngle(angle)){
                topRightCount++
            }
        }
        return topRightCount
    }

    fun getPieTopHeight(leftRightSpaceSize: Float): Float{
        val topRightCount = getTopRightCount()
        if(topRightCount > 0){
            return leftRightSpaceSize / 2 + topRightCount * getCommentContentHeight()
        }else{
            return 0f
        }

//        if(topRightCount > 0) {
//            val topTextSize = mCommentTopTextPaint?.textSize ?: 0f
//            val padding = mCommentBottomTextPadding * 2 + mCommentTopTextPadding * 2
//            val bottomTextSize = mCommentBottomTextPaint?.textSize ?: 0f
//            val lineSize = mCommentLineSize
//            val topHeight = topTextSize + padding + bottomTextSize + lineSize
//            // 加上最大高度
//            return max(leftRightSpaceSize,topHeight)
//        }
    }

    fun getPieBottomHeight(leftRightSpaceSize: Float): Float{
        val list = mList ?: return 0f
        list.forEach {
            val angle = it.startAngle + it.swipeAngle / 2f
            if(angle > 45 && angle < 135){
                val textSize = mCommentBottomTextPaint?.textSize ?: 0f
                return leftRightSpaceSize / 2 + mCommentBottomTextPadding * 2 + mLeftRightSpace / 2f + textSize
            }
        }
        return 0f
    }

    fun setLeftRightSpace(space: Float) {
        mLeftRightSpace = space
    }

}